#pragma once

#include <iostream>
#include <vector>
#include <pthread.h>
#include <string>
#include <semaphore.h>

// 环形队列实现管理
template <class T>
class Ringqueue_t
{
private:
	void P(sem_t &sem)
	{
		sem_wait(&sem);
	}

	void V(sem_t &sem)
	{
		sem_post(&sem);
	}

	void Lock(pthread_mutex_t &mutex)
	{
		pthread_mutex_lock(&mutex);
	}
	void Unlock(pthread_mutex_t &mutex)
	{
		pthread_mutex_unlock(&mutex);
	}

public:
	Ringqueue_t(int cap) :_ring_queue(cap), _cap(cap), _consumer_step(0), _producter_step(0)
	{
		sem_init(&_room_sem, 0, _cap);
		sem_init(&_data_sem, 0, 0);

		pthread_mutex_init(&_product_mutex, nullptr);
		pthread_mutex_init(&_consum_mutex, nullptr);
	}

	void Enqueue(const T &in)
	{
		// 生产行为
		P(_room_sem);						 // 锁定一个信号量
		Lock(_product_mutex);
		_ring_queue[_producter_step++] = in; // 往队列里面放任务
		_producter_step %= _cap;			 // 实现环形
		Unlock(_product_mutex);
		V(_data_sem);
	}

	void Pop(T *out)
	{
		// 消费行为
		P(_data_sem);
		Lock(_consum_mutex);
		*out = _ring_queue[_consumer_step++]; // 取任务
		_consumer_step %= _cap;
		Unlock(_consum_mutex);
		V(_room_sem);
	}

	~Ringqueue_t()
	{
		sem_destroy(&_room_sem);
		sem_destroy(&_data_sem);

		pthread_mutex_destroy(&_product_mutex);
		pthread_mutex_destroy(&_consum_mutex);
	}

private:
	std::vector<T> _ring_queue; // 用顺序表模拟实现环形队列
	int _cap;					// 环形队列的上限

	// 生产和消费的下标
	int _consumer_step;
	int _producter_step;

	// 定义信号量
	sem_t _room_sem; // 生产者关心
	sem_t _data_sem; // 消费者关心

	// 定义锁，维护多生产多消费之间的互斥关系
	pthread_mutex_t _product_mutex;
	pthread_mutex_t _consum_mutex;
};